package com.xm.util;

import java.util.HashMap;

/**
 * 找出最近的物流公司
 * @author 康文程
 * @date 2023-12-8 下午 03:35
 */
public class LogisticsUtil {
    /**
     * 物流公司的经纬度信息
     */
    private static final HashMap<Integer, double[]> LOGISTICS_COMPANIES = new HashMap<>();

    /**
     * 该方法用于向工具类中添加一个物流公司的经纬度信息。需要传入物流公司的名称、纬度和经度三个参数。
     * @param companyId 物流公司名称
     * @param latitude 公司所在位置的纬度
     * @param longitude 公司所在位置的经度
     */
    public static void addLogisticsCompany(Integer companyId, double latitude, double longitude) {
        LOGISTICS_COMPANIES.put(companyId, new double[]{latitude, longitude});
    }

    /**
     * 该方法用于计算离指定位置最近的物流公司。需要传入当前位置的纬度和经度两个参数，并返回离当前位置最近的物流公司的名称。
     * @param latitude 当前经度
     * @param longitude 当前纬度
     * @return String最近的物流公司
     */
    public static Integer getNearestCompany(double latitude, double longitude) {
        double[] myLocation = new double[]{latitude, longitude};

        Integer nearestCompany = 0;
        double minDistance = Double.MAX_VALUE;
        for (Integer companyId : LOGISTICS_COMPANIES.keySet()) {
            double[] companyLocation = LOGISTICS_COMPANIES.get(companyId);
            double distance = calculateDistance(myLocation, companyLocation);
            if (distance < minDistance) {
                minDistance = distance;
                nearestCompany = companyId;
            }
        }

        return nearestCompany;
    }

    /**
     * 该方法用于计算两个经纬度之间的距离。需要传入两个长度为 2 的 double 数组，
     * 分别表示两个位置的经纬度信息，并返回两个位置之间的距离（单位：公里）
     * @param location1 位置一经纬度信息
     * @param location2 位置二经纬度信息
     * @return double
     */
    private static double calculateDistance(double[] location1, double[] location2) {
        double earthRadius = 6371;
        // 地球半径（单位：公里）

        //使用 Math.toRadians() 方法将度数转换为弧度。
        double lat1 = Math.toRadians(location1[0]);
        double lon1 = Math.toRadians(location1[1]);
        double lat2 = Math.toRadians(location2[0]);
        double lon2 = Math.toRadians(location2[1]);

        //根据 Haversine 公式，计算两个位置纬度和经度之间的差值。
        double dLat = lat2 - lat1;
        double dLon = lon2 - lon1;

        //使用三角函数计算球面上两个位置之间的弧长。
        double a = Math.pow(Math.sin(dLat / 2), 2) + Math.cos(lat1) * Math.cos(lat2) * Math.pow(Math.sin(dLon / 2), 2);
        double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));

        //将弧长乘以地球半径，得到两个位置之间的距离。
        return earthRadius * c;
    }

    /**
     * 使用方法
     * @param args 数组
     */
    public static void main(String[] args) {
        // 添加物流公司的经纬度信息
        LogisticsUtil.addLogisticsCompany(100, 30.5928, 114.3055);
        LogisticsUtil.addLogisticsCompany(101, 39.9042, 116.4074);
        LogisticsUtil.addLogisticsCompany(102, 31.2304, 121.4737);

        // 当前位置（假设在长沙）
        double myLatitude = 28.2282;
        double myLongitude = 112.9388;

        // 获取离指定位置最近的物流公司
        Integer nearestCompany = LogisticsUtil.getNearestCompany(myLatitude, myLongitude);

        System.out.println("离您最近的物流公司是：" + nearestCompany);
    }
}
